package com.es.esapi.service.impl;

import com.alibaba.fastjson.JSON;
import com.es.esapi.common.CommonResponse;
import com.es.esapi.common.ResponseCode;
import com.es.esapi.domain.ClassA;
import com.es.esapi.domain.Doc_content;
import com.es.esapi.domain.Doc_location;
import com.es.esapi.domain.Doc_res;
import com.es.esapi.service.EsearchService;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service("esearchService")
public class EsearchServiceImpl implements EsearchService {

    @Autowired
    @Qualifier("restHighLevelClient")
    private RestHighLevelClient client;

    @Override
    public CommonResponse<Object> create_index(String index_name) throws IOException {
        CreateIndexRequest request=new CreateIndexRequest(index_name);
        CommonResponse<Object> result= exist_index(index_name);
        if(result.isSuccess()){
            CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT);
            return  CommonResponse.createForSuccess("索引创建成功");
        }
        else {
            return result;
        }
    }

    @Override
    public CommonResponse<Object> index_ini() throws IOException {
        CreateIndexRequest request=new CreateIndexRequest("doc_content_index");
        CommonResponse<Object> result= exist_index("doc_content_index");
        if(result.isSuccess()){
            CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT);
        }
        XContentBuilder builder = XContentFactory.jsonBuilder();
        builder.startObject();
        {
            builder.startObject("mappings");
            {
                builder.startObject("properties");
                {
                    builder.startObject("doc_id");
                    {
                        builder.field("type", "keyword");
                    }
                    builder.endObject();
                    builder.startObject("title");
                    {
                        builder.field("type", "keyword");
                    }
                    builder.endObject();
                    builder.startObject("location");
                    {
                        builder.field("type", "keyword");
                    }
                    builder.endObject();
                    builder.startObject("click_times");
                    {
                        builder.field("type", "keyword");
                    }
                    builder.endObject();
                    builder.startObject("favour_times");
                    {
                        builder.field("type", "keyword");
                    }
                    builder.endObject();

                }
                builder.endObject();
            }
            builder.endObject();
        }
        builder.endObject();
        CreateIndexRequest index = new CreateIndexRequest("doc_location_index");
        index.source(builder);
        CreateIndexResponse response= client.indices().create(index, RequestOptions.DEFAULT);
        return CommonResponse.createForSuccess("索引初始化成功");
    }

    @Override
    public CommonResponse<Object> exist_index(String index_name) throws IOException {
        GetIndexRequest request=new GetIndexRequest(index_name);
        boolean exists=client.indices().exists(request,RequestOptions.DEFAULT);
        if(exists){
            return  CommonResponse.createForError(ResponseCode.ERROR.getCode(),"ERROR索引已存在");
        }else {
            return  CommonResponse.createForSuccess("索引不存在");
        }
    }

    @Override
    public CommonResponse<Object> delete_index(String index_name) throws IOException {
        DeleteIndexRequest request=new DeleteIndexRequest(index_name);
        CommonResponse<Object> result= exist_index(index_name);
        if(!result.isSuccess()){
            AcknowledgedResponse acknowledgedResponse = client.indices().delete(request, RequestOptions.DEFAULT);
            if(acknowledgedResponse.isAcknowledged()){
                return CommonResponse.createForSuccess("删除成功");
            }
            return CommonResponse.createForError("删除失败");
        }
        else {
            return result;
        }
    }

    @Override
    public CommonResponse<Object> add_document(String doc_title, int page_index, String doc_content,String index_name) throws IOException {
//        暂时使用doc_title代替doc_content_index
        index_name="doc_content_index";
        String doc_id=doc_title+ String.valueOf(page_index);
        Doc_content Doc_content =new Doc_content(doc_id,doc_title,page_index,doc_content);
        IndexRequest request=new IndexRequest("doc_content_index");
        request.timeout("1s");
        request.id(doc_id);
        IndexRequest source = request.source(JSON.toJSONString(Doc_content), XContentType.JSON);
        IndexResponse indexResponse= client.index(request,RequestOptions.DEFAULT);
        return CommonResponse.createForSuccess(indexResponse.status());
    }


    @Override
    public CommonResponse<Object> is_exist_document(String doc_title, int page_index) throws IOException {
        String doc_id=doc_title+"_"+String.valueOf(page_index);
        GetRequest getRequest=new GetRequest("doc_content_index",doc_id);
        getRequest.fetchSourceContext(new FetchSourceContext(false));
        getRequest.storedFields("_none_");
        boolean exist = client.exists(getRequest, RequestOptions.DEFAULT);
        if(!exist){
            return  CommonResponse.createForSuccess("文档不存在");
        }
        else {
            return  CommonResponse.createForError("文档已存在");
        }
    }

    @Override
    public CommonResponse<Object> delete_document(String doc_title, int page_index) throws IOException {
        CommonResponse<Object> result= is_exist_document(doc_title,page_index);
        if(!result.isSuccess()){
            String doc_id=doc_title+ String.valueOf(page_index);
            DeleteRequest deleteRequest=new DeleteRequest("doc_content_index",doc_id);
            deleteRequest.timeout("1s");
            DeleteResponse deleteResponse=client.delete(deleteRequest,RequestOptions.DEFAULT);
            return CommonResponse.createForSuccess("删除成功");
        }
       else {
           return result;
        }
    }


    @Override
    public CommonResponse<Object> bulk_document(String doc_title, List<ClassA> tlist) throws IOException {
        String index_name = "doc_content_index";
        BulkRequest bulkRequest=new BulkRequest("doc_content_index");
        for (ClassA item:tlist) {
            String doc_id=doc_title+ "_"+String.valueOf(item.getPage());
            Doc_content doc_content =new Doc_content(doc_id,doc_title, item.getPage(),item.getContent());
            IndexRequest indexRequest = new IndexRequest();
            indexRequest.index(index_name);
            indexRequest.id(doc_id);
            IndexRequest source = indexRequest.source(JSON.toJSONString(doc_content), XContentType.JSON);
            /*批量存入大量请求*/
            bulkRequest.add(indexRequest);
        }
        BulkResponse resp =client.bulk(bulkRequest, RequestOptions.DEFAULT);
        return CommonResponse.createForSuccess(resp.status());
    }

    @Override
    public CommonResponse<Object> add_location_index(String title,String path) throws IOException {
        String index_name="doc_location_index";
        IndexRequest request=new IndexRequest(index_name);
        Doc_location doc_location=new Doc_location(title+"_",title,path,0,0);
        request.timeout("1s");
        request.id(doc_location.getDoc_id());
        IndexRequest source = request.source(JSON.toJSONString(doc_location), XContentType.JSON);
        IndexResponse indexResponse= client.index(request,RequestOptions.DEFAULT);
        return CommonResponse.createForSuccess(indexResponse.status());
    }

    @Override
    public CommonResponse<Object> search(String search_key, String search_mode) throws IOException {
        SearchRequest searchRequest=new SearchRequest("doc_content_index");
        SearchSourceBuilder searchSourceBuilder=new SearchSourceBuilder();
        if(Objects.equals(search_mode, "term")){ //精确搜索
            TermQueryBuilder queryBuildery= QueryBuilders.termQuery ("content",search_key);
            searchSourceBuilder.query(queryBuildery);
        }
        else if(Objects.equals(search_mode, "match")){//模糊搜索
            MatchQueryBuilder queryBuildery= QueryBuilders.matchQuery ("content",search_key);
            searchSourceBuilder.query(queryBuildery);
        }
        searchSourceBuilder.from();
        searchSourceBuilder.size();
        searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
        searchRequest.source(searchSourceBuilder);
        SearchResponse searchResponse= client.search(searchRequest,RequestOptions.DEFAULT);
        if(searchResponse.getHits().getHits().length==0){
            return  CommonResponse.createForError("未查询到结果");
        }
        System.out.println(JSON.toJSONString(searchResponse.getHits()));
        System.out.println("--------------------------------");
        Map<String, Object> res_map;
        List<Integer> Click_times_list=new ArrayList<>();
        List<Integer> Favour_times_list=new ArrayList<>();
        List<Double> content_score=new ArrayList<>();
        List<Doc_res> doc_res_list=new ArrayList<>();
        for (SearchHit documentFields:searchResponse.getHits().getHits()) {
            Map<String, Object> res = documentFields.getSourceAsMap();
            Doc_res doc_res=new Doc_res();
            doc_res.setDoc_id((String) res.get("doc_id"));
            doc_res.setScore((double)documentFields.getScore());
            content_score.add((double) documentFields.getScore());
            CommonResponse<Object> response=get_location_index(doc_res.getDoc_id().replaceAll("\\d+$", ""));
            Doc_location doc_location= (Doc_location) response.getData();
            Click_times_list.add(doc_location.getClick_times());
            doc_res.setClick_times(doc_location.getClick_times());
            Favour_times_list.add(doc_location.getFavour_times());
            doc_res.setFavour_times(doc_location.getFavour_times());
            doc_res.setDoc_location(doc_location.getLocation());
            doc_res_list.add(doc_res);
        }
        int Click_times_max=Collections.max(Click_times_list);
        int Click_times_min=Collections.min(Click_times_list);
        int Favour_times_max=Collections.max(Favour_times_list);
        int Favour_times_min=Collections.min(Favour_times_list);
        Double content_score_max=Collections.max(content_score);
        Double content_score_min=Collections.min(content_score);
        for(Doc_res item:doc_res_list){
            double score_1,score_2,score_3;
            if(Click_times_max-Click_times_min!=0){
                score_1= (item.getClick_times()-Click_times_min)*30/(Click_times_max-Click_times_min);
            }else {
                score_1=Click_times_max==0?30:0;
            }
            if(Favour_times_max-Favour_times_min!=0){
                score_2= (item.getFavour_times()-Favour_times_min)*10/(Favour_times_max-Favour_times_min);
            }else {
                score_2=Favour_times_max==0?10:0;
            }
            if(content_score_max-content_score_min!=0){
                score_3= (item.getScore()-content_score_min)*60/(content_score_max-content_score_min);
            }else {
                score_3=content_score_max==0?0:60;
            }
            item.setRes_score(score_1+score_2+score_3);
        }
        Collections.sort(doc_res_list);
        return CommonResponse.createForSuccess(doc_res_list);
    }

    @Override
    public CommonResponse<Object> get_location_index(String id) throws IOException {
        SearchRequest searchRequest=new SearchRequest("doc_location_index");
        SearchSourceBuilder searchSourceBuilder=new SearchSourceBuilder();
        TermQueryBuilder queryBuildery= QueryBuilders.termQuery ("doc_id",id);
        searchSourceBuilder.query(queryBuildery);
        searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
        searchRequest.source(searchSourceBuilder);
        SearchResponse searchResponse= client.search(searchRequest,RequestOptions.DEFAULT);
        Map<String, Object> res=null;
        Doc_location doc_location=new Doc_location();
        for (SearchHit documentFields:searchResponse.getHits().getHits()) {
            System.out.println("进循环");
            res= documentFields.getSourceAsMap();
            doc_location.setLocation((String) res.get("location"));
            doc_location.setDoc_id((String) res.get("doc_id"));
            doc_location.setClick_times((Integer) res.get("click_times"));
            doc_location.setFavour_times((Integer) res.get("favour_times"));
            doc_location.setTitle((String) res.get("title"));
        }
        return CommonResponse.createForSuccess(doc_location);
    }

    @Override
    public CommonResponse<Object> favour(String doc_id) throws IOException {
        SearchRequest searchRequest=new SearchRequest("doc_location_index");
        SearchSourceBuilder searchSourceBuilder=new SearchSourceBuilder();
        MatchQueryBuilder queryBuildery= QueryBuilders.matchQuery("doc_id",doc_id);
        searchSourceBuilder.query(queryBuildery);
        searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
        searchRequest.source(searchSourceBuilder);
        SearchResponse searchResponse= client.search(searchRequest,RequestOptions.DEFAULT);
        if(searchResponse.getHits().getHits().length==0){
            return  CommonResponse.createForError("未查询到结果");
        }
        Doc_location doc_location = new Doc_location();
        Map<String, Object> res=null;
        for (SearchHit documentFields:searchResponse.getHits().getHits()) {
            res=documentFields.getSourceAsMap();
            doc_location.setLocation((String) res.get("location"));
            doc_location.setDoc_id((String) res.get("doc_id"));
            doc_location.setClick_times((Integer) res.get("click_times"));
            doc_location.setFavour_times((Integer) res.get("favour_times"));
            doc_location.setTitle((String) res.get("title"));
        }
        int favour_times=doc_location.getFavour_times()+1;
        doc_location.setFavour_times(favour_times);
        IndexRequest request=new IndexRequest("doc_location_index");
        request.timeout("1s");
        request.id(doc_id);
        IndexRequest source = request.source(JSON.toJSONString(doc_location), XContentType.JSON);
        IndexResponse indexResponse= client.index(request,RequestOptions.DEFAULT);
        return CommonResponse.createForSuccess(indexResponse.status());
    }

    @Override
    public CommonResponse<Object> click(String doc_id) throws IOException {
        SearchRequest searchRequest=new SearchRequest("doc_location_index");
        SearchSourceBuilder searchSourceBuilder=new SearchSourceBuilder();
        MatchQueryBuilder queryBuildery= QueryBuilders.matchQuery("doc_id",doc_id);
        searchSourceBuilder.query(queryBuildery);
        searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
        searchRequest.source(searchSourceBuilder);
        SearchResponse searchResponse= client.search(searchRequest,RequestOptions.DEFAULT);
        if(searchResponse.getHits().getHits().length==0){
            return  CommonResponse.createForError("未查询到结果");
        }
        Doc_location doc_location = new Doc_location();
        Map<String, Object> res=null;

        for (SearchHit documentFields:searchResponse.getHits().getHits()) {
            res=documentFields.getSourceAsMap();
            doc_location.setLocation((String) res.get("location"));
            doc_location.setDoc_id((String) res.get("doc_id"));
            doc_location.setClick_times((Integer) res.get("click_times"));
            doc_location.setFavour_times((Integer) res.get("favour_times"));
            doc_location.setTitle((String) res.get("title"));
        }
        int click_times=doc_location.getClick_times()+1;
        doc_location.setClick_times(click_times);
        IndexRequest request=new IndexRequest("doc_location_index");
        request.timeout("1s");
        request.id(doc_id);
        IndexRequest source = request.source(JSON.toJSONString(doc_location), XContentType.JSON);
        IndexResponse indexResponse= client.index(request,RequestOptions.DEFAULT);
        return CommonResponse.createForSuccess(indexResponse.status());
    }


}
